package com.googlecode.mvcguice;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;

public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 7148170928721035917L;

	private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class);

	private List<ControllerDispatcher> dispatchers;

	@Override
	public void init() throws ServletException {
		LOGGER.debug("Init dispatcher...");
		Injector injector = (Injector) getServletContext().getAttribute(GuiceServletConextListener.INJECTOR_NAME);
		TypeLiteral<ControllerDispatcher> typeLiteral = TypeLiteral.get(ControllerDispatcher.class);

		List<Binding<ControllerDispatcher>> bindings = injector.findBindingsByType(typeLiteral);
		List<ControllerDispatcher> tmpDispatchers = new ArrayList<ControllerDispatcher>(bindings.size());
		for (Binding<ControllerDispatcher> binding : bindings) {
			tmpDispatchers.add(injector.getInstance(binding.getKey()));
		}

		LOGGER.debug("Registered {} controller dispatches", tmpDispatchers.size());

		dispatchers = tmpDispatchers;
	}

	@Override
	public void destroy() {
		dispatchers = null;
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		final boolean dispatched = dispatch(request, response);
		if (!dispatched) {
			// TODO: implement template support for error page
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
		}
	}

	private boolean dispatch(HttpServletRequest request, HttpServletResponse response) {
		final ServletContext servletContext = getServletContext();
		for (ControllerDispatcher dispatcher : dispatchers) {
			if (dispatcher.dispatch(request, response, servletContext)) {
				return true;
			}
		}
		return false;
	}
}
